package com.zlcx.tz.live.common.config;

import com.zlcx.tz.live.common.config.auth.AccessDeniedExceptionHandler;
import com.zlcx.tz.live.common.config.auth.AuthExceptionEntryPoint;
import com.zlcx.tz.live.common.config.auth.UsersBearerTokenExtractor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
import java.util.Arrays;
import java.util.List;

/**
 * 资源服务器相关配置
 * @author liude
 * @author anjl
 * 本服务作为resource接入oauth认证时，使用该配置设置resourceId以及security的过滤
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    /**
     * 作为resource设置resourceId只有client账号拥有该权限时，才能访问该resource服务
     */
    @Value("${spring.application.name}")
    String resourceId;


    /**
     * 重要！！！
     * 用于配置不需要验证token的url地址，即便传入的token非法也不会进行验证
     */
    public static final List<String> NO_AUTH_URLS = Arrays.asList("/users/login",
            "/complaint/picCheck/**",
            "/publisher/liveTask/**",
            "/unauth/**");


    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {

        resources.resourceId(resourceId)
                //自定义获取token，添加逻辑，不需要验证的url，不再拿去token
                .tokenExtractor(new UsersBearerTokenExtractor())
                //拦截器中的权限异常处理，给出统一格式
                .authenticationEntryPoint(new AuthExceptionEntryPoint()).accessDeniedHandler(new AccessDeniedExceptionHandler());
    }


    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").permitAll();
    }



    /**
     * 为了能够在@PreAuthorize中使用oauth特有的配置, 加入此项
     */
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public static class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
        @Override
        protected MethodSecurityExpressionHandler createExpressionHandler() {
            return new OAuth2MethodSecurityExpressionHandler();
        }
    }
}